+2005-06-29 Matthias Clasen <mclasen@redhat.com>
+
+ * gtk/gtkbutton.c (gtk_button_grab_broken): Handle broken
+ grabs.
+
+ * gtk/gtkrange.c (gtk_range_grab_broken): Handle broken
+ grabs.
+
+ * gdk/gdkevents.h: Add a boolean to specify wether the broken
+ grab was implicit.
+
+ * gdk/x11/gdkdisplay-x11.c (gdk_display_pointer_is_grabbed):
+ As the documentation states, don't return TRUE for
+ implicit grabs.
+
+ * gdk/x11/gdkdisplay-x11.h (struct _GdkDisplayX11): Add
+ a boolean field to store wether a pointer grab is implicit.
+
+ * gdk/x11/gdkmain-x11.c (_gdk_xgrab_check_button_event):
+ Track implicit grabs.
+
+ * gdk/x11/gdkevents-x11.c (gdk_event_translate): Call
+ _gdk_xgrab_check_button_event for button events.
+
2005-06-28 Matthias Clasen <mclasen@redhat.com>
* gtk/gtkiconview.c (gtk_icon_view_calculate_item_size2):
+2005-06-29 Matthias Clasen <mclasen@redhat.com>
+
+ * gtk/gtkbutton.c (gtk_button_grab_broken): Handle broken
+ grabs.
+
+ * gtk/gtkrange.c (gtk_range_grab_broken): Handle broken
+ grabs.
+
+ * gdk/gdkevents.h: Add a boolean to specify wether the broken
+ grab was implicit.
+
+ * gdk/x11/gdkdisplay-x11.c (gdk_display_pointer_is_grabbed):
+ As the documentation states, don't return TRUE for
+ implicit grabs.
+
+ * gdk/x11/gdkdisplay-x11.h (struct _GdkDisplayX11): Add
+ a boolean field to store wether a pointer grab is implicit.
+
+ * gdk/x11/gdkmain-x11.c (_gdk_xgrab_check_button_event):
+ Track implicit grabs.
+
+ * gdk/x11/gdkevents-x11.c (gdk_event_translate): Call
+ _gdk_xgrab_check_button_event for button events.
+
2005-06-28 Matthias Clasen <mclasen@redhat.com>
* gtk/gtkiconview.c (gtk_icon_view_calculate_item_size2):
+2005-06-29 Matthias Clasen <mclasen@redhat.com>
+
+ * gtk/gtkbutton.c (gtk_button_grab_broken): Handle broken
+ grabs.
+
+ * gtk/gtkrange.c (gtk_range_grab_broken): Handle broken
+ grabs.
+
+ * gdk/gdkevents.h: Add a boolean to specify wether the broken
+ grab was implicit.
+
+ * gdk/x11/gdkdisplay-x11.c (gdk_display_pointer_is_grabbed):
+ As the documentation states, don't return TRUE for
+ implicit grabs.
+
+ * gdk/x11/gdkdisplay-x11.h (struct _GdkDisplayX11): Add
+ a boolean field to store wether a pointer grab is implicit.
+
+ * gdk/x11/gdkmain-x11.c (_gdk_xgrab_check_button_event):
+ Track implicit grabs.
+
+ * gdk/x11/gdkevents-x11.c (gdk_event_translate): Call
+ _gdk_xgrab_check_button_event for button events.
+
2005-06-28 Matthias Clasen <mclasen@redhat.com>
* gtk/gtkiconview.c (gtk_icon_view_calculate_item_size2):
+
#ifndef __GDK_EVENTS_H__
#define __GDK_EVENTS_H__
GdkWindow *window;
gint8 send_event;
gboolean keyboard;
+ gboolean implicit;
GdkWindow *grab_window;
};
{
g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
- return (GDK_DISPLAY_X11 (display)->pointer_xgrab_window != NULL);
+ return (GDK_DISPLAY_X11 (display)->pointer_xgrab_window != NULL &&
+ !GDK_DISPLAY_X11 (display)->pointer_xgrab_implicit);
}
/**
GdkWindowObject *pointer_xgrab_window;
gulong pointer_xgrab_serial;
gboolean pointer_xgrab_owner_events;
+ gboolean pointer_xgrab_implicit;
guint32 pointer_xgrab_time;
GdkWindowObject *keyboard_xgrab_window;
}
set_user_time (window, event);
+
+ _gdk_xgrab_check_button_event (window, xevent);
break;
case ButtonRelease:
event->button.device = display->core_pointer;
set_screen_from_root (display, event, xevent->xbutton.root);
-
+
+ _gdk_xgrab_check_button_event (window, xevent);
break;
case MotionNotify:
static void
generate_grab_broken_event (GdkWindow *window,
- GdkWindow *grab_window,
- gboolean keyboard)
+ gboolean keyboard,
+ gboolean implicit,
+ GdkWindow *grab_window)
{
GdkEvent event;
event.grab_broken.window = window;
event.grab_broken.send_event = 0;
event.grab_broken.keyboard = keyboard;
+ event.grab_broken.implicit = implicit;
event.grab_broken.grab_window = grab_window;
gdk_event_put (&event);
{
GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
if (display_x11->pointer_xgrab_window != NULL &&
- display_x11->pointer_xgrab_window != window)
+ display_x11->pointer_xgrab_window != (GdkWindowObject *)window)
generate_grab_broken_event (GDK_WINDOW (display_x11->pointer_xgrab_window),
- window, FALSE);
+ FALSE, display_x11->pointer_xgrab_implicit,
+ window);
display_x11->pointer_xgrab_window = (GdkWindowObject *)window;
display_x11->pointer_xgrab_serial = serial;
display_x11->pointer_xgrab_owner_events = owner_events;
display_x11->pointer_xgrab_time = time;
+ display_x11->pointer_xgrab_implicit = FALSE;
}
return gdk_x11_convert_grab_status (return_val);
{
GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (gdk_drawable_get_display (window));
if (display_x11->keyboard_xgrab_window != NULL &&
- display_x11->keyboard_xgrab_window != window)
+ display_x11->keyboard_xgrab_window != (GdkWindowObject *)window)
generate_grab_broken_event (GDK_WINDOW (display_x11->keyboard_xgrab_window),
- window, TRUE);
+ TRUE, FALSE, window);
display_x11->keyboard_xgrab_window = (GdkWindowObject *)window;
display_x11->keyboard_xgrab_serial = serial;
if (tmp)
{
generate_grab_broken_event (GDK_WINDOW (display_x11->pointer_xgrab_window),
- NULL, FALSE);
+ FALSE, display_x11->pointer_xgrab_implicit,
+ NULL);
display_x11->pointer_xgrab_window = NULL;
}
}
if (tmp)
{
generate_grab_broken_event (GDK_WINDOW (display_x11->keyboard_xgrab_window),
- NULL, TRUE);
+ TRUE, FALSE, NULL);
display_x11->keyboard_xgrab_window = NULL;
}
}
if ((GdkWindowObject *)window == display_x11->pointer_xgrab_window)
{
generate_grab_broken_event (GDK_WINDOW (display_x11->pointer_xgrab_window),
- NULL, FALSE);
+ FALSE, display_x11->pointer_xgrab_implicit,
+ NULL);
display_x11->pointer_xgrab_window = NULL;
}
if ((GdkWindowObject *)window == display_x11->keyboard_xgrab_window)
{
generate_grab_broken_event (GDK_WINDOW (display_x11->keyboard_xgrab_window),
- NULL, TRUE);
+ TRUE, FALSE, NULL);
display_x11->keyboard_xgrab_window = NULL;
}
}
+/**
+ * _gdk_xgrab_check_button_event:
+ * @window: a #GdkWindow
+ * @event: an XEvent of type ButtonPress or ButtonRelease
+ *
+ * Checks to see if a button event starts or ends an implicit grab.
+ **/
+void
+_gdk_xgrab_check_button_event (GdkWindow *window,
+ XEvent *xevent)
+{
+ GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (gdk_drawable_get_display (window));
+
+ /* track implicit grabs for button presses */
+ switch (xevent->type)
+ {
+ case ButtonPress:
+ if (!display_x11->pointer_xgrab_window)
+ {
+ display_x11->pointer_xgrab_window = (GdkWindowObject *)window;
+ display_x11->pointer_xgrab_serial = xevent->xany.serial;
+ display_x11->pointer_xgrab_owner_events = FALSE;
+ display_x11->pointer_xgrab_time = xevent->xbutton.time;
+ display_x11->pointer_xgrab_implicit = TRUE;
+ }
+ break;
+ case ButtonRelease:
+ if (display_x11->pointer_xgrab_window &&
+ display_x11->pointer_xgrab_implicit &&
+ (xevent->xbutton.state & ~(GDK_BUTTON1_MASK << (xevent->xbutton.button - 1))) == 0)
+ {
+ display_x11->pointer_xgrab_window = NULL;
+ }
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+}
+
void
_gdk_windowing_display_set_sm_client_id (GdkDisplay *display,
const gchar *sm_client_id)
GdkEventButton *event);
static gint gtk_button_button_release (GtkWidget *widget,
GdkEventButton *event);
+static gint gtk_button_grab_broken (GtkWidget *widget,
+ GdkEventAny *event);
static gint gtk_button_key_release (GtkWidget *widget,
GdkEventKey *event);
static gint gtk_button_enter_notify (GtkWidget *widget,
widget_class->expose_event = gtk_button_expose;
widget_class->button_press_event = gtk_button_button_press;
widget_class->button_release_event = gtk_button_button_release;
+ widget_class->grab_broken_event = gtk_button_grab_broken;
widget_class->key_release_event = gtk_button_key_release;
widget_class->enter_notify_event = gtk_button_enter_notify;
widget_class->leave_notify_event = gtk_button_leave_notify;
return TRUE;
}
+static gboolean
+gtk_button_grab_broken (GtkWidget *widget,
+ GdkEventAny *event)
+{
+ GtkButton *button = GTK_BUTTON (widget);
+ gboolean save_in;
+
+ /* Simulate a button release without the pointer in the button */
+ if (button->button_down)
+ {
+ save_in = button->in_button;
+ button->in_button = FALSE;
+ gtk_button_released (button);
+ if (save_in != button->in_button)
+ {
+ button->in_button = save_in;
+ gtk_button_update_state (button);
+ }
+ }
+
+ return TRUE;
+}
+
static gboolean
gtk_button_key_release (GtkWidget *widget,
GdkEventKey *event)
GdkEventCrossing *event);
static gint gtk_range_leave_notify (GtkWidget *widget,
GdkEventCrossing *event);
+static gboolean gtk_range_grab_broken (GtkWidget *widget,
+ GdkEventGrabBroken *event);
static void gtk_range_grab_notify (GtkWidget *widget,
gboolean was_grabbed);
static void gtk_range_state_changed (GtkWidget *widget,
widget_class->scroll_event = gtk_range_scroll_event;
widget_class->enter_notify_event = gtk_range_enter_notify;
widget_class->leave_notify_event = gtk_range_leave_notify;
+ widget_class->grab_broken_event = gtk_range_grab_broken;
widget_class->grab_notify = gtk_range_grab_notify;
widget_class->state_changed = gtk_range_state_changed;
widget_class->style_set = gtk_range_style_set;
gtk_widget_queue_draw (GTK_WIDGET (range));
}
+static gboolean
+gtk_range_grab_broken (GtkWidget *widget,
+ GdkEventGrabBroken *event)
+{
+ GtkRange *range = GTK_RANGE (widget);
+
+ if (range->layout->grab_location != MOUSE_OUTSIDE)
+ {
+ if (range->layout->grab_location == MOUSE_SLIDER)
+ update_slider_position (range, range->layout->mouse_x, range->layout->mouse_y);
+
+ stop_scrolling (range);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
static gint
gtk_range_button_release (GtkWidget *widget,
GdkEventButton *event)